#pragma once

/* 实现长连接(WebSocket连接)的管理 */

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include "logger.hpp"

namespace ChatSystem
{
    //0. 定义server类型
    typedef websocketpp::server<websocketpp::config::asio> server_t;
    //连接的类型： server_t::connection_ptr;

    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>;

        struct Client
        {
            Client(const std::string& user_id, const std::string& login_session_id)
            :_user_id(user_id), _login_session_id(login_session_id)
            {}
            std::string _user_id;    //用户ID
            std::string _login_session_id;   //登录会话ID
        };

        Connection(){}
        ~Connection(){}
        
        //新增数据的接口
        void insert(const server_t::connection_ptr& conn, 
            const std::string& user_id, 
            const std::string& login_session_id)
        {
            //先加锁
            std::unique_lock<std::mutex> lock(_mutex);
            _uid_connections.insert(std::make_pair(user_id, conn));
            _connection_clients.insert(std::make_pair(conn, Client(user_id, login_session_id)));
        }

        //通过用户ID获取对应的长连接
        server_t::connection_ptr connection(const std::string& user_id)
        {
            //先加锁
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _uid_connections.find(user_id);
            if(it == _uid_connections.end())
            {
                LOG_ERROR("获取 - 未找到 {} 客户端的长连接！", user_id);
                return server_t::connection_ptr();
            }
            return it->second;
        }

        //通过长连接获取用户 ID 和登录会话 ID 的接口
        bool client(const server_t::connection_ptr& conn, std::string& user_id, std::string& login_session_id)
        {
            //先加锁
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connection_clients.find(conn);
            if(it == _connection_clients.end())
            {
                LOG_ERROR("获取 - 未找到长连接 {} 对应的客户端信息！", (size_t)conn.get());
                return false;
            }
            user_id = it->second._user_id;
            login_session_id = it->second._login_session_id;
            return true;
        }

        //移除映射关系
        bool remove(const server_t::connection_ptr& conn)
        {
            //先加锁
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connection_clients.find(conn);
            if(it == _connection_clients.end())
            {
                LOG_ERROR("删除 - 未找到长连接 {} 对应的客户端信息！", (size_t)conn.get());
                return false;
            }
            _uid_connections.erase(it->second._user_id);
            _connection_clients.erase(it);
            return true;
        }

    private:
        std::mutex _mutex;
        std::unordered_map<std::string, server_t::connection_ptr> _uid_connections;
        std::unordered_map<server_t::connection_ptr, Client> _connection_clients;
    };

}